package com.mashibing.serviceprice.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mashibing.internalcommon.constant.CommonStatusEnum;
import com.mashibing.internalcommon.dto.PriceRule;
import com.mashibing.internalcommon.dto.ResponseResult;
import com.mashibing.internalcommon.request.ForecastPriceDTO;
import com.mashibing.internalcommon.response.DirectionResponse;
import com.mashibing.internalcommon.response.ForecastPriceResponse;
import com.mashibing.serviceprice.mapper.PriceRuleMapper;
import com.mashibing.serviceprice.remote.ServiceMapClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;

/**
 * @author 史慕尧
 */
@Service
@Slf4j
public class ForecastPriceService {
    @Autowired
    ServiceMapClient serviceMapClient;
    @Autowired
    private PriceRuleMapper priceRuleMapper;

    public ResponseResult<ForecastPriceResponse> forecastPrice(String depLongitude, String depLatitude, String destLongitude, String destLatitude,String cityCode,String vehicleType) {
        log.info("出发地经纬度" + depLatitude + "...." + depLongitude);
        log.info("目的地经纬度" + destLatitude + "..." + destLongitude);
        ForecastPriceDTO forecastPriceDTO = new ForecastPriceDTO();
        forecastPriceDTO.setDepLongitude(depLongitude);
        forecastPriceDTO.setDepLatitude(depLatitude);
        forecastPriceDTO.setDestLongitude(destLongitude);
        forecastPriceDTO.setDestLatitude(destLatitude);
        log.info("调用地图服务查询距离和时长");
        ResponseResult<DirectionResponse> direction = serviceMapClient.direction(forecastPriceDTO);
        System.out.println("...." + direction.getData());
        Integer distance = direction.getData().getDistance();
        Integer duration = direction.getData().getDuration();
        log.info("读取计价规则");
        HashMap<String, Object> queryMap = new HashMap<>();
        queryMap.put("city_code", cityCode);
        queryMap.put("vehicle_type", vehicleType);
        QueryWrapper<PriceRule> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("city_code", cityCode);
        objectQueryWrapper.eq("vehicle_type", vehicleType);
        objectQueryWrapper.orderByDesc("fare_version");

        List<PriceRule> priceRules = priceRuleMapper.selectList(objectQueryWrapper);
        if (priceRules.size() == 0) {
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(), CommonStatusEnum.FAIL.getValue());
        }
        PriceRule priceRule = priceRules.get(0);

        log.info("根据距离,时长,计价规则计算价格");
        Double price=getPrice(distance,duration,priceRule);
        ForecastPriceResponse forecastPriceResponse = new ForecastPriceResponse();
        forecastPriceResponse.setPrice(price);
        forecastPriceResponse.setCityCode(cityCode);
        forecastPriceResponse.setVehicleType(vehicleType);
        return ResponseResult.success(forecastPriceResponse);
    }

    /**
     * 根据距离,时长,计价规则计算价格
     *
     * @param distance
     * @param duration
     * @param priceRule
     * @return
     */
    public static  double getPrice(Integer distance, Integer duration, PriceRule priceRule) {
        BigDecimal price = new BigDecimal(0);
        //起步价
        Double startFare = priceRule.getStartFare();
        BigDecimal startFareDecimal = new BigDecimal(startFare);
       price = price.add(startFareDecimal);
        //里程费
        //总里程单位是米
        BigDecimal distanceDecimal = new BigDecimal(distance);
        ///总里程单位是千米
        BigDecimal distanceMileDecimal = distanceDecimal.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP);
        Integer startMile = priceRule.getStartMile();
        BigDecimal startMileDecimal = new BigDecimal(priceRule.getStartMile());
        Double distanceSubtract = distanceMileDecimal.subtract(startMileDecimal).doubleValue();
        Double mile = distanceSubtract < 0 ? 0 : distanceSubtract;
        BigDecimal mileDecimal = new BigDecimal(mile);
        Double unitPricePerMile = priceRule.getUnitPricePerMile();
        BigDecimal unitPricePerMileDecimal = new BigDecimal(unitPricePerMile);
        BigDecimal mileFare = mileDecimal.multiply(unitPricePerMileDecimal.setScale(2, BigDecimal.ROUND_HALF_UP));
        price=price.add(mileFare);
        //时长费
        BigDecimal time = new BigDecimal(duration);
        //计算出分钟数timeDecimal
        BigDecimal timeDecimal = time.divide(new BigDecimal(60), 2, BigDecimal.ROUND_HALF_UP);
        //计时单价
        Double unitPricePerMinute = priceRule.getUnitPricePerMinute();
        BigDecimal unitPricePerMinuteDecimal = new BigDecimal(unitPricePerMinute);
        BigDecimal timefare = timeDecimal.multiply(unitPricePerMinuteDecimal);
       price= price.add(timefare);
        return price.doubleValue();
    }

    /**
     * 计算实际价格
     * @param distance
     * @param duration
     * @param cityCode
     * @param vehicleType
     * @return
     */
    public ResponseResult<Double> calculatePrice( Integer distance ,  Integer duration, String cityCode, String vehicleType){
        // 查询计价规则
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("city_code",cityCode);
        queryWrapper.eq("vehicle_type",vehicleType);
        queryWrapper.orderByDesc("fare_version");

        List<PriceRule> priceRules = priceRuleMapper.selectList(queryWrapper);
        if (priceRules.size() == 0){
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(),CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }

        PriceRule priceRule = priceRules.get(0);

        log.info("根据距离、时长和计价规则，计算价格");

        double price = getPrice(distance, duration, priceRule);
        return ResponseResult.success(price);
    }

    public static void main(String[] args) {
        PriceRule priceRule= new PriceRule();
        priceRule.setStartFare(10.0);
        priceRule.setUnitPricePerMile(1.8);
        priceRule.setStartMile(3);
        priceRule.setUnitPricePerMinute(0.5);

        System.out.println(ForecastPriceService.getPrice(6500, 1800, priceRule));
    }
}
